爬虫入门实战第二站

您所在的位置:网站首页 python 文本加密 爬虫入门实战第二站

爬虫入门实战第二站

#爬虫入门实战第二站| 来源: 网络整理| 查看: 265

爬虫入门实战第二站-爬取网易云歌曲评论 简介

之前的工作:爬虫入门实战第一站——梨视频视频爬取 由于csdn中无法发布爬虫的内容,就在这里发布了。 这次的任务是获取网易云音乐下面的评论,涉及的知识比上次更多,包括Js逆向的知识。 使用的python包:

execjs(运行Js文件,通过pip install PyExecJS安装) requests(发起请求) json(json数据转换)

使用浏览器:

Edge浏览器 步骤

网易云音乐网站

1.找到一首歌曲

在这里插入图片描述

2.按下F12键打开开发者模式,对其进行抓包

刷新网页进行抓包,结果如下: 在这里插入图片描述

3.查找获得评论数据的接口 方法一

点击这些接口,然后点击预览,预览里面是接口的返回数据,我们看下是否有评论数据。 在这里插入图片描述

方法二

在搜索栏搜索评论信息,找到接口,这个比上面一个一个接口分析要快。但注意如果页面加密了就不行了。 在这里插入图片描述 由此我们得到网易云评论数据的接口是:https://music.163.com/weapi/comment/resource/comments/get?csrf_token= 这里csrf_token是登录后才会有信息的。

4.对获得评论数据接口进行分析

(1)点击负载,可以看到接口的参数是进行了加密的,那我们需要找到它是如何进行加密的。 在这里插入图片描述 (2)为了找到加密过程,我们点击发起程序部分。在这里插入图片描述 这是一个调用堆栈,它的执行顺序是从下往上执行。 (3)我们点击第一个程序,也是最后才执行的,出现如下结果: 在这里插入图片描述 这里的send函数是发送信息给服务器的作用,我们需要的加密数据也通过这个函数发送,我们对它进行进一步分析。 (4)给send函数位置打一个断点,找到目标接口调用这个函数的位置。 如下图所示,我们需要的是url应该是get?csrf_token=,而不是下图所示的内容。 在这里插入图片描述 继续进行debug,知道看到我们需要的接口。 在这里插入图片描述 (5)对目标接口位置进行分析。 通过该函数后参数被加密了,我们需要找到它没加密前是在哪个位置。 在这里插入图片描述 第(4)步调试结束的位置,下面有一个调用堆栈,就是该接口调用的一些文件,也是从下往上依次执行,我们对其进行分析,找到没有加密的数据最后存在的地方。 在这里插入图片描述 我们从上往下依次寻找,最后找到这个位置: 在这里插入图片描述 因此数据的形式为:

"rid":"R_SO_4_472603422", "threadId":"R_SO_4_472603422", "pageNo":"1", "pageSize":"20", "cursor":"-1", "offset":"0", "orderType":"1", "csrf_token":""

(6)找到数据后,分析它是如何进行加密的。 打开第(5)步找到的文件并打上断点,如图所示: 在这里插入图片描述 然后刷新界面进行调试,注意接口需要是get才行: 在这里插入图片描述 然后继续运行后面的语句,发现数据加密了。 在这里插入图片描述 由此我们基本可以得到加密的语句为: var bMr1x = window.asrsea(JSON.stringify(i0x), bsg8Y(["流泪", "强"]), bsg8Y(TH5M.md), bsg8Y(["爱心", "女孩", "惊恐", "大笑"])); 那我们之后需要做的就是实现跟这个函数类似的功能。

5.构建加密函数

找到第4步的window.asrsea函数,通过在文件里面按下Ctrl+F键,然后进行搜索。 在这里插入图片描述 由此可以得到加密函数的整体框架:

function a(a) { var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = ""; for (d = 0; a > d; d += 1) e = Math.random() * b.length, e = Math.floor(e), c += b.charAt(e); return c } function b(a, b) { var c = CryptoJS.enc.Utf8.parse(b) , d = CryptoJS.enc.Utf8.parse("0102030405060708") , e = CryptoJS.enc.Utf8.parse(a) , f = CryptoJS.AES.encrypt(e, c, { iv: d, mode: CryptoJS.mode.CBC }); return f.toString() } function c(a, b, c) { var d, e; return setMaxDigits(131), d = new RSAKeyPair(b,"",c), e = encryptedString(d, a) } function d(d, e, f, g) { var h = {} , i = a(16); return h.encText = b(d, g), h.encText = b(h.encText, i), h.encSecKey = c(i, e, f), h }

对于上述加密函数的实现,有两种方式:

使用js实现,通过该文件中的函数实现加密功能,遇到缺少的函数继续在该文件中查找。补齐后通过python的库函数调用js文件实现加密功能。 使用python实现,通过分析加密函数的逻辑,实现相同的功能。

在说明下面内容之前,先看下d函数,有4个参数,再看下调用它的地方:

window.asrsea(JSON.stringify(i0x), bsg8Y(["流泪", "强"]), bsg8Y(TH5M.md), bsg8Y(["爱心", "女孩", "惊恐", "大笑"]));

我们看下它的每个参数的值,发现除了第一个参数,其他参数其实都是定值,通过运行这些函数,得到:

e = '010001' f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' g = '0CoJUm6Qyw8W8jud'

这对应d函数里面的参数,因此d函数只要传入一个字符串数据即可。

方法一

这里我说下具体思路。 对于上面的加密函数整体框架,我们一个一个补齐里面缺少的函数。 我们发现c函数中的RSAKeyPair是需要补齐的,补齐方法如下: 在这里插入图片描述 然后就找到函数了。 在这里插入图片描述 该函数里面的其他缺失函数也是用同样的方法补齐。 补齐完成后使用execjs库里面的函数进行调用,过程如下:

ctx = execjs.compile(open('补充完整的js文件地址', 'r', encoding='utf-8').read()).call('d', '输入的参数')

由此得到加密后的数据,也就是d函数返回的数据。 然后封装成参数,即:

post_data = {} post_data['params'] = ctx['encText'] post_data['encSecKey'] = ctx['encSecKey']

最后发起请求:

get_comment_url = 'https://music.163.com/weapi/comment/resource/comments/get?csrf_token=' response = requests.post(url=get_comment_url,data=post_data) 方法二

先分析a函数,很明显它是要获得一个a位的随机字符串。

function a(a) { var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = ""; for (d = 0; a > d; d += 1) e = Math.random() * b.length, e = Math.floor(e), c += b.charAt(e); return c }

然后分析b函数,它里面没有其他的随机数,都是用于加密的一些函数,因此给定固定的参数,它就是定值。

function b(a, b) { var c = CryptoJS.enc.Utf8.parse(b) , d = CryptoJS.enc.Utf8.parse("0102030405060708") , e = CryptoJS.enc.Utf8.parse(a) , f = CryptoJS.AES.encrypt(e, c, { iv: d, mode: CryptoJS.mode.CBC }); return f.toString() }

对于c函数,也是一个加密的过程,没有随机因素。

function c(a, b, c) { var d, e; return setMaxDigits(131), d = new RSAKeyPair(b,"",c), e = encryptedString(d, a) }

通过分析d函数,我们可以知道h.encText其实就是params参数,h.encSecKey其实就是encSecKey参数。对于h.encText,由于d对于不同的歌曲来说是不同的,所以我们需要手动实现加密过程。 然后对于 h.encSecKey,e和f都是定值,i我们在运行过程中获得,那么h.encSecKey就是一个定值,所以我们直接用运行过程中得到的i和h.encSecKey就行。

function d(d, e, f, g) { var h = {} , i = a(16); return h.encText = b(d, g), h.encText = b(h.encText, i), h.encSecKey = c(i, e, f), h }

下面开始完成python代码。

首先,在运行过程中,我们得到i和h.encSecKey的值: 在这里插入图片描述

i = 'ompBdaIcEweDSvm0' def get_encSecKey(): return "ByfLFqCAkOx5zSR+99lUdjEA9eCX9cDOLq/BrIAllXsAVuqJ64yyGo7DXxAN5UhksFOalcMawpjJhZP3wVfqmhBdCbxSSZvY4zblYWx8T34wkJVfRxzYnfmuYm3iRIqoAYcFjLzKvogEbOIwqYx7vWyob+neQC/TzS7uYK2VH7LhWTveYQ/4PXVk1lUyA3puYYTlvQ3TGfUThGzBRa0sw1poUwGsIUfI1UkhQpzCO1UZlev/3HkweKWwsRmLntYp6Mq2feSKOfuNu+tgJyLEeiwM9ZEkXrqJjepzwEeMzc8="

然后完成b函数的功能,这里使用了AES类,是Crypto里面的。

def enc_parmas(data,key): iv = "0102030405060708" data = to_16(data) aes = AES.new(key=key.encode("utf-8"),IV=iv.encode("utf-8"),mode=AES.MODE_CBC) bs = aes.encrypt(data.encode("utf-8")) return str(b64encode(bs),"utf-8")

最后得到h.encText,也就是params参数。

def get_params(data): fisrt = enc_parmas(data,g) second = enc_parmas(fisrt,i) return second

得到接口需要的参数后发起请求就可以得到评论数据了。需要注意传入的data参数是json字符串格式的。

6.获取评论数据

通过发起请求后得到的内容为: 在这里插入图片描述

我们将其转换为json格式

response.encoding = 'utf-8' json_resp = response.json()

然后获得json数据里面的评论数据:

comments = json_resp['data']['comments'] for comment in comments: content = comment['content'] print(content)

其他数据也可以获得,这需要自己分析json数据了。如评论数量:

total_comment_num = json_resp['data']['totalCount'] 全部代码 使用Js文件

Js文件目前没有提供,可以私聊我获取。

import json import execjs import requests get_comment_url = 'https://music.163.com/weapi/comment/resource/comments/get?csrf_token=' data = { "rid":"R_SO_4_472603422", "threadId":"R_SO_4_472603422", "pageNo":"1", "pageSize":"20", "cursor":"-1", "offset":"0", "orderType":"1", "csrf_token":"" } # 转换为json字符串 json_string = json.dumps(data) # 调用json文件 ctx = execjs.compile(open('encry.js', 'r', encoding='utf-8').read()).call('d', json_string) print(ctx) # 组成提交的数据 post_data = {} post_data['params'] = ctx['encText'] post_data['encSecKey'] = ctx['encSecKey'] # print(post_data) response = requests.post(url=get_comment_url,data=post_data) 只使用python from Crypto.Cipher import AES # pip install pycryptodome from base64 import b64encode import requests import json def get_encSecKey(): return "ByfLFqCAkOx5zSR+99lUdjEA9eCX9cDOLq/BrIAllXsAVuqJ64yyGo7DXxAN5UhksFOalcMawpjJhZP3wVfqmhBdCbxSSZvY4zblYWx8T34wkJVfRxzYnfmuYm3iRIqoAYcFjLzKvogEbOIwqYx7vWyob+neQC/TzS7uYK2VH7LhWTveYQ/4PXVk1lUyA3puYYTlvQ3TGfUThGzBRa0sw1poUwGsIUfI1UkhQpzCO1UZlev/3HkweKWwsRmLntYp6Mq2feSKOfuNu+tgJyLEeiwM9ZEkXrqJjepzwEeMzc8=" def to_16(data): pad = 16 - len(data) % 16 data += chr(pad) * pad return data def get_params(data): fisrt = enc_parmas(data,g) second = enc_parmas(fisrt,i) return second def enc_parmas(data,key): iv = "0102030405060708" data = to_16(data) aes = AES.new(key=key.encode("utf-8"),IV=iv.encode("utf-8"),mode=AES.MODE_CBC) bs = aes.encrypt(data.encode("utf-8")) return str(b64encode(bs),"utf-8") get_comment_url = 'https://music.163.com/weapi/comment/resource/comments/get?csrf_token=' data = { "rid": "R_SO_4_1325905146", "threadId": "R_SO_4_1325905146", "pageNo": "1", "pageSize": "2000", "cursor": "-1", "offset": "0", "orderType": "1", "csrf_token": "" } e = '010001' f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' g = '0CoJUm6Qyw8W8jud' i = 'ompBdaIcEweDSvm0' post_data = {} post_data['params'] = get_params(json.dumps(data)) post_data['encSecKey'] = get_encSecKey() resp = requests.post(url=get_comment_url,data=post_data) resp.encoding = 'utf-8' json_resp = resp.json() # print(json_resp) comments = json_resp['data']['comments'] for comment in comments: content = comment['content'] print(content) 小结与展望

以上就是网易云音乐评论获取的全部内容了,其实该套加密程序在网易云音乐里面的其他功能也有使用,因此掌握了该方法其他功能也可以进行尝试,如网易云的搜索。 除此之外,data里面的rid的值R_SO_4_1325905146中1325905146其实就是歌词的id,因此可以改变它来获取不同的歌曲的评论,也可以通过改变pageSize来获取每页评论的数目。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3